Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Search and Replace Widget #1755

Merged
merged 1 commit into from
May 17, 2018
Merged

Search and Replace Widget #1755

merged 1 commit into from
May 17, 2018

Conversation

jbicker
Copy link
Contributor

@jbicker jbicker commented Apr 20, 2018

Search in workspace allows the user to search the whole workspace for textual occurences.
By default it searches for all text occurrences in all files in workspace case insensitive.

One can refine the search result by selecting "Match Case", "Match Whole Words" and "Use Regular Expressions" as well as using include and exclude fields with glob patterns.

The result tree is navigable by keyboard using cursor keys.

Additional control buttons above the search form will update the search results, collapse the result tree or reset the search form.

One can remove unwanted occurrences from the result tree by clicking the x on the right side of every tree element.

In addition to searching for text occurrences in the workspace the possibility to replace all matches are provided. The replace form field is hidden by default and can be expanded by clicking the small button on the left side of the search field.

In replace mode the selection of a result opens a diff editor widget where the left side shows the
original and the right side a preview with the replacements.

One is able to replace all or single occurrences in workspace.

@svenefftinge svenefftinge changed the title [WIP] Search and Replace Widget implemented [WIP] Search and Replace Widget Apr 20, 2018
@jbicker jbicker force-pushed the SearchAndReplaceInWorkspace branch from 1b2a8d8 to bd9c5c1 Compare April 20, 2018 11:56
@jbicker jbicker changed the title [WIP] Search and Replace Widget Search and Replace Widget implemented Apr 20, 2018
@svenefftinge svenefftinge changed the title Search and Replace Widget implemented Search and Replace Widget Apr 20, 2018
Copy link
Member

@akosyakov akosyakov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've noticed that the search does not find everything for me. Try to search for foo, it finds storage-service.spec.ts then adjust to fo, it does not find it anymore. Should be fixed separately?

@@ -0,0 +1,6 @@
<!--Copyright (c) Microsoft Corporation. All rights reserved.-->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jbicker please check that files have our copyrights in addition

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

const widget = currentTitle.owner;
const result = this.resultTree.get(widget.editor.uri.withoutScheme().toString());
if (result) {
this.decorateEditor(result, widget);
Copy link
Member

@akosyakov akosyakov Apr 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cases when result are undefined should be handled as well otherwise decoration won't be ever removed

return new URI(uri).withScheme(MEMORY_TEXT).withQuery(lines.join("\n"));
}

protected decorateEditor(node: ResultNode, editorWidget: EditorWidget) {
Copy link
Member

@akosyakov akosyakov Apr 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The following code should handle removing decorations:

    protected decorateEditor(node: ResultNode | undefined, editorWidget: EditorWidget) {
        const oldDecorations = this.appliedDecorations.get(key) || [];
        const appliedDecorations = editorWidget.editor.deltaDecorations({
            newDecorations: this.createEditorDecorations(node),
            oldDecorations,
            uri: editorWidget.editor.uri.toString()
        });
        this.appliedDecorations.set('search-in-workspace-matches', appliedDecorations);
    }

* Replaces the text of source given in ReplacetextParams.
* @param params: ReplaceTextParams
*/
replaceText(params: ReplaceTextParams): Promise<boolean>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better to have the general solution: #1756

Please open a follow-up issue to refactor it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -142,6 +142,12 @@ is not optimized for dense, information rich UIs.
--theia-removed-color0: rgba(230, 0, 0, 0.8);
--theia-modified-color0: rgba(0, 100, 150, 0.8);

--theia-search-match-color0: rgba(234, 92, 0, 0.33);
Copy link
Member

@akosyakov akosyakov Apr 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we consider to move them to the search in workspace extension? They are not supposed to be used in core. If it is hard, please at least file a follow-up issue to make it easier to define themed variables for extensions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved them to the extension and added new variables here. Not the best solution, a bit arbitrary maybe. I guess we should edit this with #1486.

Regarding themed variables for extensions: we shouldn't do such thing and leave every theme related variable in core.

@@ -29,4 +49,16 @@ export default new ContainerModule(bind => {
const client = ctx.container.get(SearchInWorkspaceClientImpl);
return WebSocketConnectionProvider.createProxy(ctx.container, '/search-in-workspace', client);
}).inSingletonScope();

bind(MemoryTextResourceResolver).toSelf().inSingletonScope();
Copy link
Member

@akosyakov akosyakov Apr 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about InMemoryTextResource?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, sounds better.

import { MEMORY_TEXT } from "./memory-text-resource";
import { FileResourceResolver } from "@theia/filesystem/lib/browser";

export interface ResultNode extends ExpandableTreeNode, SelectableTreeNode {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about putting supplementary types under SearchInWorkspaceResultTreeWidget. ResultNode, ResultLineNode sound generic. please review for other generic top level concepts

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok


protected changeEmitter: Emitter<Map<string, ResultNode>>;

constructor(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -0,0 +1,315 @@
.searchContainer {
Copy link
Member

@akosyakov akosyakov Apr 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please review for missing copyrights in css

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

background: var(--theia-icon-clear);
}

.searchContainer .searchHeader .search-field {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use more specific top level css class names to avoid collisions: theia-search-in-workspace-container

@kittaakos was suggesting to use t- prefix instead to make it shorter: t-siw-container

We can discuss css convention on next dev meeting, agree on something as a team and follow it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@jbicker jbicker force-pushed the SearchAndReplaceInWorkspace branch 2 times, most recently from 43e34d2 to bf219ec Compare April 25, 2018 13:49
@svenefftinge
Copy link
Contributor

svenefftinge commented Apr 30, 2018

  • The toolbar icons on the top
    • are too big.
    • need cursor: pointer;
    • need a title (hover)
  • The state should be kept on reload.
  • Results should auto-update on type or any change to the options.
  • An icon for include all that passes the -uu option is needed.
  • The existing Search in Workspace command should open the view.
  • When the view is activated the search input should get focus.
  • 'files to include' option doesn't work for me. I expected glob patterns relative to the workspace to work. Probably the same issue exists with 'files to exclude'? Also when provided the '-uu' option should be passed automatically.
  • The scroll bar covers the icons on the right hand side of the list, so they are hard to click. A little bit of space could help.
  • The number showing the matches is hard to read on dark theme (grey on grey)
  • when replacing individual items in one file one by one, the diff editor is being opened after the first item.

@jbicker jbicker force-pushed the SearchAndReplaceInWorkspace branch from 8024ad7 to 53b4380 Compare April 30, 2018 12:39
@jbicker jbicker changed the title Search and Replace Widget [WIP] Search and Replace Widget May 7, 2018
@jbicker jbicker force-pushed the SearchAndReplaceInWorkspace branch 7 times, most recently from 92fd1b9 to 42e4397 Compare May 9, 2018 11:39
@jbicker jbicker changed the title [WIP] Search and Replace Widget Search and Replace Widget May 9, 2018
@jbicker jbicker force-pushed the SearchAndReplaceInWorkspace branch from 42e4397 to 60fa482 Compare May 9, 2018 12:05
@svenefftinge
Copy link
Contributor

svenefftinge commented May 10, 2018

The existing Search in Workspace command should open the view.

It still opens the old search command. It should be completely replaced with this (i.e. remove the existing functionality).

The alignment of the include/exclude input fields is not good:

screen shot 2018-05-10 at 21 57 45

@jbicker jbicker force-pushed the SearchAndReplaceInWorkspace branch 2 times, most recently from 93cb8f1 to 6eec2e2 Compare May 14, 2018 08:21
Copy link
Contributor

@svenefftinge svenefftinge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jbicker jbicker force-pushed the SearchAndReplaceInWorkspace branch from 43936ac to b52950b Compare May 14, 2018 13:18
@kittaakos
Copy link
Contributor

@jbicker, here is an earlier issue that was dealing with vscode-ripgrep problems on Windows: [windows] Workspace search is broken. I hope it helps to identify the test failures on AppVeyor. Ping me if you need assistance.

children: []
};

model.onSelectionChanged(nodes => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it will leak, please collect all listeners

exclude: [],
maxResults: 500
};
this.resultTreeWidget.onChange(r => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it will leak, please collect all listeners with this.toDispose.push

const node = nodes[0];
if (SearchInWorkspaceResultLineNode.is(node)) {
this.doOpen(node, true);
}
});
}));

model.onNodeRefreshed(() => this.changeEmitter.fire(this.resultTree));
Copy link
Member

@akosyakov akosyakov May 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this event listener also should be captured, please review all new widgets in this PR that they capture all event listeners

@svenefftinge
Copy link
Contributor

seems like we are back to only flaky tests failing.
@jbicker could you squash the changes?

Signed-off-by: Jan Bicker <jan.bicker@typefox.io>
@jbicker jbicker force-pushed the SearchAndReplaceInWorkspace branch from 8eb712e to 84b26f7 Compare May 17, 2018 06:42
@svenefftinge
Copy link
Contributor

Cool, please merge

@jbicker jbicker merged commit 4996f9b into master May 17, 2018
@simark
Copy link
Contributor

simark commented May 18, 2018

Hi Jan,

Awesome work! Could you add a test that searches for a string that contains a double quote? I think it now fails because we use shell: true.

You can also input fun things like

salut"; echo prout > /tmp/lol; "

which writes to /tmp/lol... So either we should not use shell: true, or we should sanitize the input.

@jbicker
Copy link
Contributor Author

jbicker commented May 18, 2018

@simark, thanks for the hint. I will take care of it.
shell:true is actually needed, otherwise the glob patterns do not work.

@kittaakos
Copy link
Contributor

Also, please clean up the branch if you do not need it, @jbicker. Thanks!

@simark
Copy link
Contributor

simark commented May 18, 2018

@simark, thanks for the hint. I will take care of it.
shell:true is actually needed, otherwise the glob patterns do not work.

Can you explain why? From what I understand, the glob expressions are handled by rg, the shell should not play a role. More over, we probably don't want to depend on the particular shell that runs in the backend, different shells can have different behaviors.

@svenefftinge svenefftinge deleted the SearchAndReplaceInWorkspace branch May 18, 2018 14:56
@jbicker
Copy link
Contributor Author

jbicker commented May 22, 2018

@simark: honestly I don't see anymore what the problem was without the shell option. So I removed it and also the quotes around the search term and the glob terms. So rg should handle the arguments, right?
The tests are running successfully and in theia it is working too.
Please check this PR: #1931

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants